import { IRes } from '@/interface'
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'
import moment from 'moment'
import { Observable } from 'rxjs'
import { map } from 'rxjs/operators'
import { CustomLoggerService } from '..'

@Injectable()
export class ResponseInterceptor implements NestInterceptor {
    constructor(private readonly logger: CustomLoggerService) {}

    public intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
        const ctx = context.switchToHttp()
        const startTime = process.hrtime()
        const response = ctx.getResponse()
        return next.handle().pipe(
            map((data: any) => {
                const endTime = process.hrtime()
                const responseTime =
                    ((endTime[0] * 1e9 + endTime[1]) / 1e6 - (startTime[0] * 1e9 + startTime[1]) / 1e6).toFixed(3) +
                    'ms'
                const timestamp = Number(moment().format('x'))
                response.status(200)
                if (['string', 'number', 'undefined'].includes(typeof data)) {
                    this.logger.filterLog(context, null, null, data)
                    return data
                }
                if (data?.isBuffer) {
                    response.setHeader('Content-Type', data.ct)
                    response.setHeader('Content-disposition', data.cd)
                    response.setHeader('Content-Length', data.cl)
                    response.end(Buffer.from(data.data, 'binary'))
                    this.logger.filterLog(context, null, null, { length: data.cl })
                    return
                }

                const res: IRes<any> = { flag: 1, data: {}, message: 'success', timestamp, responseTime }
                res.flag = data?.flag || 1
                res.data = data?.data || data
                res.message = data?.message || 'success'
                if (/^\d{2,5}$/.test(res.data.flag)) {
                    delete res.data.flag
                }
                if (res.data.message) {
                    delete res.data.message
                }
                this.logger.filterLog(context, null, null, res)
                return res
            }),
        )
    }
}
